#define TX //SET CODE AS DEFAULT TX
#define BEACON_LOOP //leave defined for infinite RF beacon mode

#define LAMBDA_STR "Lambda Board RF v0.3\n"

#define LED_PIN 5
#define LED_PORT PORTB
#define LED_DDR DDRB

#define BUZZER_PORT PORTA
#define BUZZER_PIN 4


#include <avr/io.h> 
#include <util/delay.h> 
#include <stdio.h>

//#include "a2d.h"

#include "global.h"
#include "serial.h"
#include "uart2.h"
#include "RF24G.h"
#include "cmdline.h"
///////////////////////////////
#include "vt100.h"		// include vt100 terminal support
#include "cmdline.h"	// include cmdline function library
#include "rprintf.h"	// include printf function library
// global variables
u08 Run;

// functions
void goCmdline(void);
void exitFunction(void);
void helpFunction(void);
void dumpArgsStr(void);
void dumpArgsInt(void);
void dumpArgsHex(void);
////////////////////////////

extern u08 data_array[4];		
//#define F_CPU 8000000UL
void rf_test(void);
void initSerialTest(void);
void InitADC(void);
void sampleAD(void);
void terminal_test(void);
void buzzerPOST(void);
void LEDPOST(void);

//State machine code from Cypress MPPT ChargeController
enum eState{Init, Start, MPPT, ConstCurrent, TrickleCharge, LoadEnable, StatusUpdate, Fault};

unsigned char bCurState;

void InitState(void);
void StartState(void);

void (*CallStateMachine[8])(void) = { 
     &InitState,			/* Initialize User Modules, Power Core & constants */
     &StartState, 			/* Check all error conditions, determine operating state & ensure safe start */
    // &MPPTState,  			/* Test for the MPPT point, park the panel at this point and track this point */
    // &ConstCurrentState,   /* For fully depleted batteries, charge the battery at Constant Current */
    // &TrickleChargeCVState,  /* For a almost charged battery, trickle charge it till it reaches a full charge */
    // &LoadEnableState, 	/* When a dusk condition is detected enable the load */
    // &StatusUpdateState, 	/* Save the system parameters in EEPROM */
/*	  &FaultState*/ }; 		/* Give the fault indication & Wait for fault condition recovery */


/*
ISR(USART0_RX_vect )      
{
	// service UART0 receive interrupt
	//cmdflg = 1;	
	uartReceiveService(0);
}
*/

//HANDLER FOR RANDOM INTERRUPTS
//http://www.nongnu.org/avr-libc/user-manual/group__avr__interrupts.html
//External Pin, Power-on Reset, Brown-out Reset, Watchdog Reset, and JTAG AVR Rese
ISR(BADISR_vect)
{
   	//PCIF1 15:8
	if(EIFR & (1<<PCIF1))
	{
	  printf("Pin Change interrupt\n");

	}	
}

///////////////printf -> uart
    static int uart_putchar(char c, FILE *stream);

    static FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL,
                                             _FDEV_SETUP_WRITE);

    static int
    uart_putchar(char c, FILE *stream)
    {

      if (c == '\n')
        uart_putchar('\r', stream);
      loop_until_bit_is_set(UCSRA, UDRE);
      UDR = c;
      return 0;
    }

/////////
int main(void)
{  

  bCurState = Init;
  
  serialInit();
  stdout = &mystdout;
  
  printf(LAMBDA_STR);
  buzzerPOST();
  LEDPOST();
  
  /*
  printf("\ndata types:\n");
  printf("u08: %x\n", sizeof(u08));
  printf("u16: %x\n", sizeof(u16));
  printf("u32: %x\n", sizeof(u32));
  */
  //serialTest();
  
  #ifdef BEACON_LOOP
    printf("ENTERING RF BEACON LOOP\n");
    rf_test();
  #endif
  
  
  //a2dInit();

 // InitState();//Initialize the User Modules
     // PORTB = 0xFF; //pullups?
 // outp(0xff,DDRB);            /* use all pins on PortB for output */

	
//baudrate calculation test
	u32 baudrate = 115200;
	u32 bauddiv = ((F_CPU+(baudrate*8L))/(baudrate*16L)-1);
	//uartSendByte(CAM_UART, bauddiv);
	//uartSendByte(CAM_UART, bauddiv>>8);
	printf("bauddiv: %02x\n", (u08)bauddiv >> 8);
	printf("bauddiv: %02x\n", (u08)bauddiv);
	
	//rf_test();

  //blink LED, Atmega325p uses PG5 as external reset, nice fail
  //sbi(DDRG, 5);
  //sbi(DDRE, 5);
  
  rprintfInit(uart0SendByte);
  //terminal_test();
  vt100Init();
  goCmdline();
  
  Run = TRUE;
  
  while(Run)
  {
	//CallStateMachine[bCurState]();   //Call the current state function  
    cmdlineMainLoop();//process command lines
	
    //_delay_ms(100); 
    //sbi(LED_PORT, LED_PIN);
   // _delay_ms(100);
    //cbi(LED_PORT, LED_PIN); 
  }	
  return 0;	  												  
}

void InitState()
{
	bCurState += 1;
	return;
}
void StartState()
{
	bCurState += 1;
	return;
}

void rf_test()
{
        //power on RF module from pin, hah
		RFDDR |= _BV(RFGNDPIN);
		cbi(RFPORT, RFGNDPIN);
		
		#ifdef TX
			configure_transmitter();
		#else
			configure_receiver();
		#endif
		
	    data_array[0] = 'l';
        data_array[1] = 'a';
        data_array[2] = 'm';
        
		#ifdef BEACON_LOOP
			while(1) {
				counter++; 
				data_array[3] = counter;
				transmit_data();
				_delay_ms(1);
			}
		#endif
		
		counter++;
        


 //       printstr("Sending data...\n");
//       
		#ifdef TX
			transmit_data();
			printstr("Data Sent\n");
		#endif
		
		configure_receiver();
		
        //Here we monitor how many clock cycles it takes for the receiver to register good data
        //elasped_time is in cycles - each cycles is 500ns at 8MHz so 541 cycles = 270.5us
        //==============================================
/*       
	   TMR1IF = 0;
        TMR1L = 0 ; TMR1H = 0 ; TMR1ON = 1;
        while(RX_DR == 0)
            if (TMR1IF == 1) break; //If timer1 rolls over waiting for data, then break
        TMR1ON = 0;
        elapsed_time.high8 = TMR1H;
        elapsed_time.low8 = TMR1L;
        printf("Time to receive = %d\n\r", elapsed_time);
		*/
        //==============================================
        printstr("Awaiting RX_DR assertion...\n");
		
		while( (RFPIN & _BV(RX_DR)) == 0);
		
        if((RFPIN & _BV(RX_DR))) //We have data!
            receive_data();
        else
            printstr("No data found!\n");
        
        _delay_ms(1000); //Have a second between transmissions just for evaluation
}

void buzzerPOST(void)
{
	//BUZZER POST
  printf("BUZZER POST\n");
  sbi(DDRA, BUZZER_PIN);  //set output
  sbi(BUZZER_PORT, BUZZER_PIN); 
  _delay_ms(250);
  cbi(BUZZER_PORT, BUZZER_PIN); 
}
void LEDPOST(void)
{
    sbi(LED_DDR, LED_PIN);              
    cbi(LED_PORT, LED_PIN);              
	_delay_ms(250); 
	sbi(LED_PORT, LED_PIN);
	_delay_ms(250);
	cbi(LED_PORT, LED_PIN);
}

//-----------------------------
/*
void Initialization(void)
{
    char tst;           // dummy

    OSCCAL_calibration();       // calibrate the OSCCAL byte
        
    CLKPR = (1<<CLKPCE);        // set Clock Prescaler Change Enable

    // set prescaler = 8, Inter RC 8Mhz / 8 = 1Mhz
    CLKPR = (1<<CLKPS1) | (1<<CLKPS0);

    // Disable Analog Comparator (power save)
    ACSR = (1<<ACD);

    // Disable Digital input on PF0-2 (power save)
    DIDR0 = (7<<ADC0D);

    // mt PORTB = (15<<PORTB0);       // Enable pullup on 
    PORTB = (15<<PB0);       // Enable pullup on 
    // mt PORTE = (15<<PORTE4);
    PORTE = (15<<PE4);

    sbiBF(DDRB, 5);               // set OC1A as output
    sbiBF(PORTB, 5);              // set OC1A high
            
    Button_Init();              // Initialize pin change interrupt on joystick
    
    RTC_init();                 // Start timer2 asynchronous, used for RTC clock

    Timer0_Init();              // Used when playing music etc.

    USART_Init(12);             // Baud rate = 9600bps
    
    DF_SPI_init();              // init the SPI interface to communicate with the DataFlash
    
    tst = Read_DF_status();

    DF_CS_inactive;             // disable DataFlash
        
    LCD_Init();                 // initialize the LCD
}
*/


//code from
//http://www.engr.sjsu.edu/bjfurman/courses/ME106/ME106pdf/A2D_ATmega128.pdf
void initADC(void)
{

}

void terminal_test(void)
{
	//cmdlineInit();
	//cmdlineMainLoop();
	
/*
    while(1)    
    {
        Term_Send( Term_Get() );                // Echo forever...
    }
	*/
}
////////////////////////////////////////

void goCmdline(void)
{
	u08 c;

	// print welcome message
	vt100ClearScreen();

	vt100SetCursorPos(1,0);

	rprintfProgStrM(LAMBDA_STR);

	// initialize cmdline system
	cmdlineInit();

	// direct cmdline output to uart (serial port)
	cmdlineSetOutputFunc(uart0SendByte);

	// add commands to the command database
	//cmdlineAddCommand("exit",		exitFunction);
	cmdlineAddCommand("help",		helpFunction);
	cmdlineAddCommand("dumpargs1",	dumpArgsStr);
	cmdlineAddCommand("dumpargs2",	dumpArgsInt);
	cmdlineAddCommand("dumpargs3",	dumpArgsHex);
	
	cmdlineAddCommand("buzz",	buzzerPOST);
	cmdlineAddCommand("blink", LEDPOST);
	cmdlineAddCommand("rftest", rf_test);
	// send a CR to cmdline input to stimulate a prompt
	cmdlineInputFunc('\r');

	// set state to run
	//Run = TRUE;
 // cmdlineMainLoop();
	// main loop
	/*
	while(Run)
	{
		// pass characters received on the uart (serial port)
		// into the cmdline processor
		//while(uartReceiveByte(0,&c)) cmdlineInputFunc(c);
		// run the cmdline execution functions
		cmdlineMainLoop();
	}
*/
	//rprintfCRLF();
	//rprintf("Exited program!\r\n");
}

void exitFunction(void)
{
	// to exit, we set Run to FALSE
	Run = FALSE;
}

void helpFunction(void)
{
	rprintfCRLF();

	rprintf("Available commands are:\r\n");
	rprintf("help      - displays available commands\r\n");
	rprintf("dumpargs1 - dumps command arguments as strings\r\n");
	rprintf("dumpargs2 - dumps command arguments as decimal integers\r\n");
	rprintf("dumpargs3 - dumps command arguments as hex integers\r\n");
	rprintf("buzz - buzzerPOST\r\n");
	rprintf("blink - \r\n");
	rprintf("rftest - \r\n");
	//rprintf("ports
	rprintfCRLF();
}

void dumpArgsStr(void)
{
	rprintfCRLF();
	rprintf("Dump arguments as strings\r\n");

	rprintfProgStrM("Arg0: "); rprintfStr(cmdlineGetArgStr(0)); rprintfCRLF();
	rprintfProgStrM("Arg1: "); rprintfStr(cmdlineGetArgStr(1)); rprintfCRLF();
	rprintfProgStrM("Arg2: "); rprintfStr(cmdlineGetArgStr(2)); rprintfCRLF();
	rprintfProgStrM("Arg3: "); rprintfStr(cmdlineGetArgStr(3)); rprintfCRLF();
	rprintfCRLF();
}

void dumpArgsInt(void)
{
	rprintfCRLF();
	rprintf("Dump arguments as integers\r\n");

	// printf %d will work but only if your numbers are less than 16-bit values
	//rprintf("Arg1 as int: %d\r\n", cmdlineGetArgInt(1));
	//rprintf("Arg2 as int: %d\r\n", cmdlineGetArgInt(2));
	//rprintf("Arg3 as int: %d\r\n", cmdlineGetArgInt(3));

	// printfNum is good for longs too
	rprintf("Arg1 as int: "); rprintfNum(10, 10, TRUE, ' ', cmdlineGetArgInt(1)); rprintfCRLF();
	rprintf("Arg2 as int: "); rprintfNum(10, 10, TRUE, ' ', cmdlineGetArgInt(2)); rprintfCRLF();
	rprintf("Arg3 as int: "); rprintfNum(10, 10, TRUE, ' ', cmdlineGetArgInt(3)); rprintfCRLF();
	rprintfCRLF();
}

void dumpArgsHex(void)
{
	rprintfCRLF();
	rprintf("Dump arguments as hex integers\r\n");

	rprintf("Arg1 as hex: "); rprintfNum(16, 8, FALSE, ' ', cmdlineGetArgHex(1)); rprintfCRLF();
	rprintf("Arg2 as hex: "); rprintfNum(16, 8, FALSE, ' ', cmdlineGetArgHex(2)); rprintfCRLF();
	rprintf("Arg3 as hex: "); rprintfNum(16, 8, FALSE, ' ', cmdlineGetArgHex(3)); rprintfCRLF();
	rprintfCRLF();
}
